----------------------------------------------------------------------------------------------------------------------------------
--[[

    等级系统

]]--
----------------------------------------------------------------------------------------------------------------------------------
---
    local function GetReplica(self)
        return self.inst.replica.hutao_com_level_sys or self.inst.replica._.hutao_com_level_sys
    end
    local function SetLevel(self,value)
        local replica_com = GetReplica(self)
        if replica_com then            
            replica_com:SetLevel(value)
        end
    end
    local function SetExp(self,value)
        local replica_com = GetReplica(self)
        if replica_com then
            replica_com:SetExp(value)
        end
    end
    local function SetExpMax(self,value)
        local replica_com = GetReplica(self)
        if replica_com then
            replica_com:SetExpMax(value)
        end
    end
----------------------------------------------------------------------------------------------------------------------------------
local hutao_com_level_sys = Class(function(self, inst)
    self.inst = inst
    -------------------------------------------------------
    ---
        self.DataTable = {}
        self.TempTable = {}
        self._onload_fns = {}
        self._onsave_fns = {}
    -------------------------------------------------------
    ---
        self.level = 0
        self.level_max = 10
        self:AddOnSaveFn(function()
            self:Set("level",self.level)
            self:Set("level_max",self.level_max)
        end)
        self:AddOnLoadFn(function()
            self.level = self:Get("level",0)
            self.level_max = self:Get("level_max",10)
        end)
    -------------------------------------------------------
    ---
        self.exp_temp_pool = 0 --- 临时经验池,用来给大量经验时连续升级使用
        self.exp = 0
        self.exp_max = 100
        self:AddOnSaveFn(function()
            self:Set("exp",self.exp)
            self:Set("exp_max",self.exp_max)
            self:Set("exp_temp_pool",self.exp_temp_pool)
        end)
        self:AddOnLoadFn(function()
            self.exp = self:Get("exp",0)
            self.exp_max = self:Get("exp_max",100)
            self.exp_temp_pool = self:Get("exp_temp_pool",0)
        end)
    -------------------------------------------------------
    --- 升级锁（用来突破）
        self.level_up_locker = {}
        self.level_up_unlocker_fn = {} -- 返回true后执行突破
        self:SyncData()
    -------------------------------------------------------
    --- 突破锁记录器
        self.level_up_unlocked = {}
        self:AddOnSaveFn(function()
            self:Set("level_up_unlocked",self.level_up_unlocked)
        end)
        self:AddOnLoadFn(function()
            self.level_up_unlocked = self:Get("level_up_unlocked",{})
        end)
        self.inst:ListenForEvent("hutao_com_level_sys.level_up_break",function(_,_table)
            local level = _table and _table.level
            if level then
                table.insert(self.level_up_unlocked,level)
            end
            self:SyncData()
        end)
    -------------------------------------------------------
    --- CLIENT 来的控制命令
        self.inst:ListenForEvent("hutao_com_level_sys.LevelUpBreak.server",function()
            self:LevelUpBreak()
        end)
        self.inst:ListenForEvent("hutao_com_level_sys.SyncData.server",function()
            self:SyncData()
        end)
    -------------------------------------------------------
end,
nil,
{
    level = SetLevel,
    exp = SetExp,
    exp_max = SetExpMax,
})
------------------------------------------------------------------------------------------------------------------------------
--- 同步数据
    function hutao_com_level_sys:SyncData()
        if self.__sync_task then
            self.__sync_task:Cancel()
            self.__sync_task = nil
        end
        self.__sync_task = self.inst:DoTaskInTime(0.1,function()
            local replica_com = GetReplica(self)
            if replica_com ~= nil then
                local data = {}
                data.__sync_flag = not self.__sync_flag
                ------------------------------------------------------------------
                -- level_up_locker
                    for i = 1, self:GetLevelMax(), 1 do
                        self.level_up_locker[i] = self.level_up_locker[i] or false
                    end
                    data.level_up_locker = self.level_up_locker
                ------------------------------------------------------------------
                --- level_up_unlocked
                    data.level_up_unlocked = self.level_up_unlocked
                ------------------------------------------------------------------
                replica_com:SyncData(data)
                self.__sync_flag = not self.__sync_flag
            end
            self.__sync_task = nil
        end)
    end
------------------------------------------------------------------------------------------------------------------------------
--- 突破锁
    function hutao_com_level_sys:SetLevelUpLocker(key,fn)
        self.level_up_locker[key] = true
        self.level_up_unlocker_fn[key] = fn
        self:SyncData()
    end
    function hutao_com_level_sys:CanLevelUp()
        return not self.level_up_locker[self.level]
    end
    function hutao_com_level_sys:IsLevelUpLocking()
        if self.level_up_locker[self.level] and self.exp > self.exp_max then
            return true
        end
        return false
    end
------------------------------------------------------------------------------------------------------------------------------
--- 参数配置+操作
    function hutao_com_level_sys:SetExpMax(value)  --- 最大经验
        self.exp_max = value
    end
    function hutao_com_level_sys:GetExpMax()    --- 最大经验
        return self.exp_max
    end
    function hutao_com_level_sys:SetExpMaxRefreshFn(fn) --- 最大经验刷新函数
        self._exp_max_refresh_fn = fn
    end
    function hutao_com_level_sys:DoExpMaxRefresh()  --- 最大经验刷新函数
        if self._exp_max_refresh_fn then
            self._exp_max_refresh_fn()
        end
    end
    function hutao_com_level_sys:SetExp(value)  --- 当前经验
        self.exp = value
    end
    function hutao_com_level_sys:GetExp()   --- 当前经验
        return self.exp
    end
    function hutao_com_level_sys:SetLevel(value) --- 当前等级
        local old_level = self.level
        self.level = value
        self.inst:PushEvent("hutao_com_level_sys.level_changed",{
            old = old_level,
            new = self.level,
        })
    end
    function hutao_com_level_sys:GetLevel() --- 当前等级
        return self.level
    end
    function hutao_com_level_sys:SetLevelRefreshFn(fn) --- 等级变更刷新函数
        self._level_refresh_fn = fn
    end
    function hutao_com_level_sys:DoLevelRefresh()   --- 等级变更刷新函数
        if self._level_refresh_fn then
            self._level_refresh_fn()
        end
    end
    function hutao_com_level_sys:LevelUp()   --- 升级
        local old_level = self.level
        self:SetLevel(math.clamp(self.level + 1, 0, self.level_max))
        if self.level ~= old_level then
            self:DoLevelRefresh()
            self:DoExpMaxRefresh()
        end
    end
    function hutao_com_level_sys:LevelDown() -- 降级
        self:SetLevel(math.clamp(self.level - 1, 0, self.level_max))
        self:DoLevelRefresh()
        self:DoExpMaxRefresh()
        self.exp = 0
        self.exp_temp_pool = 0
    end
    function hutao_com_level_sys:LevelUpBreak() -- 锁定等级的时候，强制升级
        if self.level_up_locker[self.level] and self.level_up_unlocker_fn[self.level] then
            if self.level_up_unlocker_fn[self.level](self.inst) then
                local exp_pool = self.exp_temp_pool + self.exp
                -- print("经验池储存了", exp_pool)
                self.exp_temp_pool = 0
                self:LevelUp()
                self:DoLevelRefresh()
                self:DoExpMaxRefresh()
                self.exp = math.clamp(exp_pool,0,self.exp_max-1) -- 舍弃多余的经验
                self.inst:PushEvent("hutao_com_level_sys.level_up_break",{
                    level = self.level,
                })
            end
        end
    end
    function hutao_com_level_sys:SetLevelMax(value) --- 等级上限
        self.level_max = value
    end
    function hutao_com_level_sys:GetLevelMax() --- 等级上限
        return self.level_max
    end    
------------------------------------------------------------------------------------------------------------------------------
--- 经验增加
    function hutao_com_level_sys:ExpDoDelta(value)
        if not self:CanLevelUp() then -- 不能升级的时候，经验储存到临时经验池
            self.exp = self.exp + value
            self.inst:PushEvent("hutao_com_level_sys.level_up_locking")
            return
        end
        self.exp_temp_pool = self.exp + value
        while self.exp_temp_pool >= self.exp_max do
            self.exp_temp_pool = self.exp_temp_pool - self.exp_max
            self:LevelUp()
            self:DoExpMaxRefresh()
            if not self:CanLevelUp() then -- 不能升级的时候
                self.inst:PushEvent("hutao_com_level_sys.level_up_locking")
                break
            end
        end
        self.exp = self.exp_temp_pool
        self.exp_temp_pool = 0
    end
------------------------------------------------------------------------------------------------------------------------------
----- onload/onsave 函数
    function hutao_com_level_sys:AddOnLoadFn(fn)
        if type(fn) == "function" then
            table.insert(self._onload_fns, fn)
        end
    end
    function hutao_com_level_sys:ActiveOnLoadFns()
        for k, temp_fn in pairs(self._onload_fns) do
            temp_fn(self)
        end
    end
    function hutao_com_level_sys:AddOnSaveFn(fn)
        if type(fn) == "function" then
            table.insert(self._onsave_fns, fn)
        end
    end
    function hutao_com_level_sys:ActiveOnSaveFns()
        for k, temp_fn in pairs(self._onsave_fns) do
            temp_fn(self)
        end
    end
------------------------------------------------------------------------------------------------------------------------------
----- 数据读取/储存

    function hutao_com_level_sys:Get(index,default)
        if index then
            return self.DataTable[index] or default
        end
        return nil or default
    end
    function hutao_com_level_sys:Set(index,theData)
        if index then
            self.DataTable[index] = theData
        end
    end

    function hutao_com_level_sys:Add(index,num,min,max)
        if index then
            if min and max then
                local ret = (self.DataTable[index] or 0) + ( num or 0 )
                ret = math.clamp(ret,min,max)
                self.DataTable[index] = ret
                return ret
            else
                self.DataTable[index] = (self.DataTable[index] or 0) + ( num or 0 )
                return self.DataTable[index]
            end
        end
        return 0
    end
------------------------------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------------------------------
    function hutao_com_level_sys:OnSave()
        self:ActiveOnSaveFns()
        local data =
        {
            DataTable = self.DataTable
        }
        return next(data) ~= nil and data or nil
    end

    function hutao_com_level_sys:OnLoad(data)
        if data.DataTable then
            self.DataTable = data.DataTable
        end
        self:ActiveOnLoadFns()
    end
------------------------------------------------------------------------------------------------------------------------------
return hutao_com_level_sys







